package com.songxh.application.impl;

import com.alibaba.fastjson.JSONObject;
import com.songxh.application.api.RegisterService;
import com.songxh.application.dto.RegisterInfoDTO;
import com.songxh.application.dto.RegisterParamDTO;
import com.songxh.core.entity.UserContext;
import com.songxh.core.exception.BizException;
import com.songxh.core.modle.RoleInfoDTO;
import com.songxh.core.shared.constant.RedisConsts;
import com.songxh.core.utils.DateUtils;
import com.songxh.core.utils.JWTUtils;
import com.songxh.core.utils.RedisUtils;
import com.songxh.domain.service.api.SysRoleService;
import com.songxh.domain.service.api.SysUserRoleService;
import com.songxh.domain.service.api.SysUserService;
import com.songxh.infrastructure.db.pojo.SysRole;
import com.songxh.infrastructure.db.pojo.SysUser;
import com.songxh.infrastructure.db.pojo.SysUserRole;
import com.songxh.shared.enums.PassWordEnum;
import com.songxh.shared.enums.RoleEnum;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.apache.commons.codec.digest.DigestUtils;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

/**
 * @author songxh
 * @create 2023-01-04-11:26
 */
@Service
public class RegisterServiceImpl implements RegisterService {

    @Autowired
    private SysUserService sysUserService;

    @Autowired
    private SysUserRoleService sysUserRoleService;

    @Autowired
    private SysRoleService sysRoleService;

    /**
     * 注册
     * 注意：注册的账号皆是 “用户” 身份，管理员等特殊角色只能由管理员来创建
     *
     * @param registerParamDTO
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public RegisterInfoDTO register(RegisterParamDTO registerParamDTO) {
        //判断该账号是否存在
        Integer count = sysUserService.lambdaQuery()
                .eq(SysUser::getAccount, registerParamDTO.getAccount())
                .count();
        if (count > 0) {
            throw new BizException("该用户已存在");
        }
        //校验昵称是否被注册
        Integer nickNameCount = sysUserService.lambdaQuery()
                .eq(SysUser::getNickName, registerParamDTO.getNickName())
                .count();
        if (nickNameCount > 0) {
            throw new BizException("该昵称已存在");
        }
        //创建用户
        SysUser sysUser = new SysUser();
        sysUser.setAccount(registerParamDTO.getAccount());
        sysUser.setEmail(registerParamDTO.getEmail());
        sysUser.setNickName(registerParamDTO.getNickName());
        sysUser.setPassword(DigestUtils.md5Hex(registerParamDTO.getPassword() + PassWordEnum.PASS_WORD_ENUM.getDesc()));
        sysUser.setMobilePhoneNumber(registerParamDTO.getMobilePhoneNumber());
        sysUser.setLastLogin(DateUtils.format(new Date(), DateUtils.DEFAULT_DATE_TIME_FORMAT));
        sysUser.setCreateDate(DateUtils.format(new Date(), DateUtils.DEFAULT_DATE_TIME_FORMAT));
        boolean save = sysUserService.save(sysUser);
        if (!save) {
            throw new BizException("注册时保存失败");
        }

        //创建角色用户关联信息
        //注册的都是普通用户
        SysUserRole sysUserRole = new SysUserRole();
        sysUserRole.setUserId(sysUser.getId());
        SysRole role = sysRoleService.lambdaQuery()
                .eq(SysRole::getRole_code, RoleEnum.S_NORMAL_USER.getCode())
                .one();
        sysUserRole.setRoleId(role.getId());
        boolean userRoleSave = sysUserRoleService.save(sysUserRole);
        if (!userRoleSave){
            throw new BizException("注册时角色关联失败");
        }

        JSONObject tokenData = new JSONObject();
        tokenData.put("account", sysUser.getAccount());
        tokenData.put("userId", sysUser.getId());
        String tokenKey = String.format(RedisConsts.S_Token_ACCESS_KEY, sysUser.getAccount(), sysUser.getId());
        //创建token
        String token = JWTUtils.creatJWTToken(JSONObject.parseObject(tokenData.toJSONString(), Map.class), UUID.randomUUID().toString());
        RedisUtils.set(tokenKey, token, RedisConsts.DEFAULT_EXPIRE_TIME_SECONDS);

        //将用户信息存入redis
        UserContext userContext = new UserContext();
        BeanUtils.copyProperties(sysUser, userContext);
        //角色信息
        List<RoleInfoDTO> roleInfoDTO = new ArrayList<>();
        RoleInfoDTO roleInfo = new RoleInfoDTO();
        BeanUtils.copyProperties(role, roleInfo);
        roleInfoDTO.add(roleInfo);
        userContext.setRoleInfoDTOS(roleInfoDTO);
        userContext.setSalt(PassWordEnum.PASS_WORD_ENUM.getDesc());
        String userInfoKey = String.format(RedisConsts.S_USER_INFO_KEY, sysUser.getAccount(), sysUser.getId());
        RedisUtils.set(userInfoKey, userContext);

        RegisterInfoDTO registerInfoDTO = new RegisterInfoDTO();
        BeanUtils.copyProperties(sysUser, registerInfoDTO);
        registerInfoDTO.setAccessToken(token);

        return registerInfoDTO;
    }
}
